package com.bang.study.jvm.metespace;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * @ClassName: CglibTest
 * @Desc: ASM cglib测试
 * @auther: BANG
 * @Date: 2019/09/29 09:16
 * @Version: 1.0
 * @Modified By:
 * @VM -XX:MetaspaceSize=10m -XX:MaxMetaspaceSize=10m -Xmx20m -Xmx20m
 * 思考题:java动态代理和CGLIB动态代理的区别?
 * 1. java动态代理只能对实现了接口的类进行代理.java动态代理是基于java的反射机制实现的,
 *    生成的类是Proxy的子类,并且实现了被代理类的接口.
 *    java的动态代理不会导致内存溢出.通过查看Proxy.newProxyInstance()方法的源代码,
 *    我们会发现,他会将根据我们所传的类加载器和接口,去生成class对象,然后缓存下来,
 *    当下次再调用Proxy.newProxyInstance()方法时,如果能从缓存中查找到,则直接返回,
 *    否则的话会重新生成class对象并缓存下来.
 * 2. CGLIB是针对类实现代理，主要是对指定的类生成一个子类，覆盖其中的方法,它是使用动态字节码技术实现的
 *    因为是继承，所以该类或方法最好不要声明成final.
 *    CGLIB使用不当是有可能造成内存溢出的,当调用enhancer.setUseCache(false)时,
 *    每一次都会生成一个新的class对象.
 *
 *
 *
 *
 *
 */
public class CglibTest {

    /**
     * -XX:MetaspaceSize=20m -XX:MaxMetaspaceSize=20m -XX:+TraceClassLoading -XX:+TraceClassUnloading -Xms20m -Xmx20m -verbose:class
     * -XX:MetaspaceSize=20m -XX:MaxMetaspaceSize=20m -XX:+HeapDumpOnOutOfMemoryError -Xms20m -Xmx20m
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        Thread.sleep(30000);

        while (true) {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(SonServiceImpl.class);
            enhancer.setUseCache(false);
            enhancer.setCallback(new MethodInterceptor() {
                @Override
                public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
//                    System.out.println("before method run...");
                    Object result = proxy.invokeSuper(obj, args);
//                    System.out.println("after method run...");
                    return result;
                }
            });
            SonServiceImpl sonService = (SonServiceImpl) enhancer.create();
            sonService.run("小明");
        }

    }
}
